import base64
import time
import sys
from ucloudbiz.server.vm.deployvirtualmachine import deployVirtualMachine
from ucloudbiz.server.vm.listavailableproducttypes import listAvailableProductTypes
from ucloudbiz.server.vm.listvirtualmachines import listVirtualMachines
from ucloudbiz.server.portforwarding.listfirewallrules import listFirewallRules
from ucloudbiz.server.lib.queryAsyncJobResult import queryAsyncJobResult
from ucloudbiz.server.address.listpublicipaddresses import listPublicIpAddresses
from ucloudbiz.server.portforwarding.createportforwardingrule import createPortForwardingRule

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s')
logger = logging.getLogger('ucloud-hpc')
hdlr = logging.FileHandler('/root/hpc/log/product.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.DEBUG)

TIMEOUT=20
offering = None

def findOffering(result):
    output = result['listavailableproducttypesresponse']
    producttypes = output['producttypes']
    for producttype in producttypes:
    	templatedesc = producttype['templatedesc']
	productstate = producttype['productstate']
	if templatedesc.lower() == 'centos 5.8 64bit' and productstate == 'available':
	   print "\n"
	   print "#" * 50
	   print "ServiceOfferingDesc : ", producttype['serviceofferingdesc']
	   print "DiskOfferingDesc    : ", producttype['diskofferingdesc']
	   print "ServiceOfferingID   : ", producttype['serviceofferingid']
	   print "TemplateID          : ", producttype['templateid']
	   print "DiskOfferingID      : ", producttype['diskofferingid']
	   print "ZoneID              : ", producttype['zoneid']
           yn = raw_input("Select(y/n)?")
           if yn.lower() == 'y':
               #return data for deployVM
               #return (producttype['
               profile = {'serviceofferingid': producttype['serviceofferingid'],
                          'templateid'       : producttype['templateid'],
                          'diskofferingid'   : producttype['diskofferingid'],
                          'zoneid'           : producttype['zoneid']
                          }
               logger.debug("Selected product(%s):\n%s\n" % (producttype['serviceofferingdesc'], profile))
               return profile
                          

def filterVM(result):
    #assume result is dictionary of virtualmachine
    logger.debug(result)
    d = result
    output = {}
    output['id']     = d['id']
    output['name']   = d['name']
    if d.has_key('password'):
        output['password'] = d['password']

    return output

def createSSH(url, apikey, secret):
    inst = listFirewallRules(url, apikey, secret)
    print inst.execute()
    inst = listPublicIpAddresses(url, apikey, secret)
    p = {}
    print inst.execute(p)
    print "\n\n\n"
    ipaddressid = raw_input("ipaddressid=>")
    virtualmachineid = raw_input("virtualmachineid=>")
    #find ipaddress id
    p = {
        'ipaddressid' : ipaddressid,
        'privateport' : 22,
        'protocol'    : 'TCP',
        'publicport'  : 22,
        'virtualmachineid':virtualmachineid,
        'openfirewall' : 'true',
        }

    yn = raw_input("Create SSH Portforwarding(y/n)")
    if yn.lower() == "y":
        inst = createPortForwardingRule(url,apikey,secret)
        print inst.execute(p)

def createVNC(url, apikey, secret):
    inst = listFirewallRules(url, apikey, secret)
    print inst.execute()
    inst = listPublicIpAddresses(url, apikey, secret)
    p = {}
    print inst.execute(p)
    print "\n\n\n"
    ipaddressid = raw_input("ipaddressid=>")
    virtualmachineid = raw_input("virtualmachineid=>")
    #find ipaddress id
    p = {
        'ipaddressid' : ipaddressid,
        'privateport' : 5800,
        'protocol'    : 'TCP',
        'publicport'  : 5800,
        'virtualmachineid':virtualmachineid,
        'openfirewall' : 'true',
        }

    yn = raw_input("Create VNC(TCP 5800,5900) Portforwarding(y/n)")
    if yn.lower() == "y":
        inst = createPortForwardingRule(url,apikey,secret)
        print inst.execute(p)
        p['privateport'] = 5900
        p['publicport'] = 5900
        print inst.execute(p)

def createCM(url, apikey, secret):
    inst = listFirewallRules(url, apikey, secret)
    print inst.execute()
    inst = listPublicIpAddresses(url, apikey, secret)
    p = {}
    print inst.execute(p)
    print "\n\n\n"
    ipaddressid = raw_input("ipaddressid=>")
    virtualmachineid = raw_input("virtualmachineid=>")
    #find ipaddress id
    p = {
        'ipaddressid' : ipaddressid,
        'privateport' : 8086,
        'protocol'    : 'TCP',
        'publicport'  : 8086,
        'virtualmachineid':virtualmachineid,
        'openfirewall' : 'true',
        }

    yn = raw_input("Create CM Portforwarding(y/n)")
    if yn.lower() == "y":
        inst = createPortForwardingRule(url,apikey,secret)
        print inst.execute(p)

def createHPC(url, apikey, secret):
    """
    create HPC Cluster
    """

    yn = raw_input("Find Offering(y/n)")
    if yn.lower() == "y":
        inst = listAvailableProductTypes(url, apikey, secret)
        params = {}
        result = inst.execute(params)
        offering = inst.parseJsonResult(result)
        p = findOffering(offering)
    else:
        p = {}
        p['serviceofferingid'] = raw_input('serviceofferingid=>')
        p['templateid']        = raw_input('templateid       =>')
        p['diskofferingid']    = raw_input('diskofferingid   =>')
        p['zoneid']            = raw_input('zoneid           =>')
        
    hostname = raw_input("Hostname:")
    numNodes = raw_input("Number of Compute node:")
    userdata = base64.b64encode("cloudutils.update(src=http://14.63.252.33/cloud_config-0.1.0-py2.4.egg, log=/var/log/cloudugtils.txt);cloudcfg.hpc.pbs.head(cluster.node=%s);" % numNodes)
    p['name'] = hostname
    p['userdata'] = userdata
    

    yn = raw_input("Create Head Node(y/n) ")
    query_list = {}
    inst = deployVirtualMachine(url, apikey, secret)
    if yn.lower() == "y":
        result = inst.execute(p)
        args = inst.parseJsonResult(result)
        jobid = inst.parseAsyncResult(args)
        query_list[ p['name'] ] = jobid
        logger.debug("jobid: %s" % jobid)

    count = raw_input("How many compute node(2~N) ")
    if int(count) > 0:
        n = findOffering(offering)
        n['userdata'] = base64.b64encode("cloudutils.update(src=http://14.63.252.33/cloud_config-0.1.0-py2.4.egg, log=/var/log/cloudugtils.txt);cloudcfg.hpc.pbs.node();")

    for i in range(int(count)):
        nodeid = 'node%.3d' % (i+1)
        n['name'] = nodeid
        result = inst.execute(n)
        args = inst.parseJsonResult(result)
        jobid = inst.parseAsyncResult(args)
        query_list[nodeid] = jobid

    showDic(query_list)
    
    time.sleep(60) #1minute sleep
    query = queryAsyncJobResult(url, apikey, secret)
    nodes = query_list.keys()
    nodes.sort()

    vminfos = {}
    for node in nodes:
        for i in range(TIMEOUT):
            p = {'jobid':query_list[node]}
            result = query.execute(p)
            args = query.parseJsonResult(result)
            (jobstatus,jobinfo) = query.getResult(args)
            if jobstatus == 1:
                #parse passwd
                #jobresult': {u'virtualmachine'
                vminfo = (jobinfo['jobresult'])['virtualmachine']
                vm = filterVM(vminfo)
                vminfos[node] = vm
                break
            logger.debug("%s status %s" % (node, jobstatus))
            time.sleep(30)
            
    logger.debug(showDic(vminfos))

    yn = raw_input("Create Port Forwarding(y/n)")
    if yn.lower() == "y":
        #PortForwarding
        createSSH(url, apikey, secret)

    yn = raw_input("Create CM Port Forwarding(y/n)")
    if yn.lower() == "y":
        createCM(url, apikey, secret)
        
def showDic(dic):
    #assume key = dict
    keys = dic.keys()
    keys.sort()
    msg = "#"*40 + "\nkey\tvalue\n" + "-" * 40 + "\n"
    for key in keys:
        msg = msg + "%s\t%s\n" % (key, dic[key])
    return msg


if __name__ == "__main__":
   from optparse import OptionParser
   usage = "usage: %prog [options] arg"
   parser = OptionParser()

   parser.add_option("-a","--apikey", dest="apikey",help="API Key")
   parser.add_option("-s","--secret", dest="secret",help="Secret Key")
   parser.add_option("-u","--url", dest="url",help="API Server URL")

   (options,args) = parser.parse_args()

   if not options.apikey:
       apikey = raw_input("APIKEY=>")

   else:
       apikey = options.apikey	

   if not options.secret:
       secret = raw_input("SECRET=>")
   else:
       secret = options.secret

   if not options.url:
       url = "https://api.ucloudbiz.olleh.com/server/v1/client/api?"
       
   else:
       url = options.url

   logger.debug("############## Start to deployVM #############")
   logger.debug("APIKEY:%s" % apikey)
   logger.debug("SECRET:%s" % secret)

   print "\n\n\n\n"
   print "########### Warning ###########################"
   print "API URL : %s" % url
   print "###############################################"
   print "\n\n"
   yn = raw_input("URL is corrent(y/n)")
   if yn.lower() != "y":
       print "Exiting...."
       sys.exit()

   msg = """
   1. create Full HPC
   2. update SSH firewall(tcp:22)
   3. update CM firewall(tcp:8086)
   4. update VNC firewall(tcp:5800,5900)
   ==>
   """
   choice = raw_input(msg)
   if choice == "1":
       print "Create Full HPC"
       print createHPC(url, apikey, secret)
   elif choice == "2":
       print "Update SSH firewall(tcp:22)"
       print createSSH(url, apikey, secret)
   elif choice == "3":
       print "Update CM firewall(tcp:8086)"
       print createCM(url, apikey, secret)

   elif choice == "4":
       print "Update VNC firewall(tcp:5800,5900)"
       print createVNC(url, apikey, secret)
       
   sys.exit()

   

